package cn.edu.buaa.treehole.service;

import cn.edu.buaa.treehole.config.Settings;
import cn.edu.buaa.treehole.dao.PostDao;
import cn.edu.buaa.treehole.dao.ReplyDao;
import cn.edu.buaa.treehole.dao.SignatureDao;
import cn.edu.buaa.treehole.dao.exception.*;
import cn.edu.buaa.treehole.pojo.PostInfo;
import cn.edu.buaa.treehole.pojo.PostInfoWithTagMap;
import cn.edu.buaa.treehole.pojo.dao.PostDaoInfo;
import cn.edu.buaa.treehole.pojo.dao.ReplyDaoInfo;
import cn.edu.buaa.treehole.pojo.dao.SignatureDaoInfo;
import cn.edu.buaa.treehole.pojo.network.get.PostNetworkInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Set;

@Service
public class PostInfoService {
    private final int postCacheSize = 32;

    private final Logger logger = LoggerFactory.getLogger(PostInfoService.class);
    private final PostDao postDao;
    private final ReplyDao replyDao;
    private Settings settings;
    private ReplyInfoService replyInfoService;
    private ContentService contentService;
    private NameService nameService;
    private SignatureService signatureService;
    private TagService tagService;


    @Autowired
    public PostInfoService(PostDao postDao, ReplyDao replyDao) {
        this.postDao = postDao;
        this.replyDao = replyDao;
    }

    @Autowired
    @Qualifier("defaultSetting")
    public void setSettings(Settings settings) {
        this.settings = settings;
    }

    @Autowired
    public void setReplyInfoService(ReplyInfoService replyInfoService) {
        this.replyInfoService = replyInfoService;
    }

    @Autowired
    public void setNameService(NameService nameService) {
        this.nameService = nameService;
    }

    @Autowired
    public void setContentService(ContentService contentService) {
        this.contentService = contentService;
    }

    @Autowired
    public void setTagService(TagService tagService) {
        this.tagService = tagService;
    }

    @Autowired
    public void setSignatureService(SignatureService signatureService) {
        this.signatureService = signatureService;
    }

    @Override
    public String toString() {
        return "PostInfoService{" +
                "postCacheSize=" + postCacheSize +
                ", postDao=" + postDao +
                ", replyDao=" + replyDao +
                ", replyInfoService=" + replyInfoService +
                '}';
    }

    /*
    * @param postInfo: pid不必设置.
    * */
    @Transactional(rollbackFor = {DaoException.class, RuntimeException.class})
    public synchronized long addPost(PostInfo postInfo) throws PidHasExistException, DaoException {
        long pid = postDao.selectMaxPid();
        postInfo.setPid(++pid);
        System.out.println(postInfo.getPid()+postInfo.getSignature());
        signatureService.allocNidAndInsertSignatureForPost(pid, postInfo.getSignature());

        ReplyDaoInfo replyDaoInfo = new ReplyDaoInfo();
        replyDaoInfo.setPid(postInfo.getPid());
        replyDaoInfo.setRid(0);
        replyDaoInfo.setSignature(postInfo.getSignature());
        replyDaoInfo.setTime(postInfo.getDate());
        replyDao.insertReply(replyDaoInfo);

        contentService.addPostContent(pid, postInfo.getContent());

        tagService.addTagsForPost(postInfo.getTidList(), postInfo.getPid());

        PostDaoInfo postDaoInfo = new PostDaoInfo();
        postDaoInfo.setPid(postInfo.getPid());
        postDaoInfo.setTitle(postInfo.getTitle());
        postDao.insertPost(postDaoInfo);


        return pid;
    }

    @Transactional(rollbackFor = {DaoException.class, RuntimeException.class})
    public synchronized void deletePost(long pid, String signature) throws SignatureNotExistException, DaoException {
        ReplyDaoInfo info = replyDao.selectReplyById(pid, 0);
        System.out.println(pid+" "+signature);
        System.out.println("admin=" + settings.getAdminSignature());
        boolean a = signature.equals(settings.getAdminSignature());
        boolean b = info.getSignature().equals(signature);
        if (!a && !b) {
            throw new SignatureNotExistException(toString() +
                    ".deletePost(" + pid + ", " + signature + ")");
        }
        postDao.deletePostByPid(pid);

        tagService.deleteAllTagsForPost(pid);

        contentService.deleteAllPostContent(pid);

        replyInfoService.deleteAllReplyByPid(pid);

    }

    public PostInfoWithTagMap getPostInfo(long pid) throws PidNotExistException, DaoException {
        PostInfoWithTagMap postInfoWithTagMap = new PostInfoWithTagMap();

        postInfoWithTagMap.setPid(pid);

        PostDaoInfo postDaoInfo = postDao.selectPostByPid(pid);
        postInfoWithTagMap.setTitle(postDaoInfo.getTitle());

        postInfoWithTagMap.setContent(contentService.getPostContent(pid));

        ReplyDaoInfo replyDaoInfo = replyDao.selectReplyById(pid, 0);
        postInfoWithTagMap.setTime(replyDaoInfo.getTime());
        postInfoWithTagMap.setTags(tagService.getAllTagsForPid(pid));

        return postInfoWithTagMap;
    }

    public int getRepliesCount(long pid) throws PidNotExistException, DaoException {
        return replyDao.selectAllReplyByPid(pid).size();
    }
}
